package cn.tj212.xiaoyin.common.web;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;

/**
 * 用于springmvc @ResponseBody转码
 */
public class UTF8MessageConverter extends AbstractHttpMessageConverter<String> {

    public static final Charset DEFAULT_CHARSET=Charset.forName("UTF-8");
    private final Charset defaultCharset;
    private final List<Charset> availableCharsets;
    private boolean writeAcceptCharset;

    public UTF8MessageConverter() {
        this(DEFAULT_CHARSET);
    }

    public UTF8MessageConverter(Charset defaultCharset) {
        super(new MediaType[]{new MediaType("text","plain",defaultCharset),MediaType.ALL});
        this.defaultCharset = defaultCharset;
        this.writeAcceptCharset=true;
        this.availableCharsets=new ArrayList(Charset.availableCharsets().values());
    }

    public void setWriteAcceptCharset(boolean writeAcceptCharset) {
        this.writeAcceptCharset = writeAcceptCharset;
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }

    @Override
    protected String readInternal(Class<? extends String> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        Charset charset=getContentTypeCharset(httpInputMessage.getHeaders().getContentType());
        return StreamUtils.copyToString(httpInputMessage.getBody(),charset);
    }

    @Override
    protected Long getContentLength(String s, MediaType contentType) throws IOException {
        Charset charset=getContentTypeCharset(contentType);
        try {
            return Long.valueOf(s.getBytes(charset.name()).length);
        }catch (UnsupportedCharsetException e){
            throw new IllegalStateException(e);
        }
    }

    private Charset getContentTypeCharset(MediaType contentType) {
        if ((contentType!=null)&&(contentType.getCharset()!=null)){
            return contentType.getCharset();
        }
        return this.defaultCharset;
    }

    @Override
    protected void writeInternal(String s, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        if (this.writeAcceptCharset){
            httpOutputMessage.getHeaders().setAcceptCharset(getAcceptCharsets());
        }
        Charset charset=getContentTypeCharset(httpOutputMessage.getHeaders().getContentType());
        StreamUtils.copy(s,charset,httpOutputMessage.getBody());
    }

    private List<Charset> getAcceptCharsets() {
        return this.availableCharsets;
    }
}
